import { Graph } from '@antv/x6'
import { cloneDeep } from 'lodash-es'
import ActivityNode from '@/views/approvalFlow/components/ActivityNode.vue'
import { register } from '@antv/x6-vue-shape'
export default {
  data() {
    return {
      currentZoomScale: 1,
      historyState: {
        canRedo: false,
        canUndo: false
      },
      keyboard: {
        ctrl: false
      }
    }
  },
  created() {

  },
  mounted() {

  },
  methods: {
    registerEvent() {
      const nodeConfig = {
        start: {
          width: 60,
          height: 60,
          strokeWidth: 2,
          text: '开始'
        },

        end: {
          width: 60,
          height: 60,
          strokeWidth: 3,
          text: '结束'
        },

        and: {
          width: 60,
          height: 60,
          text: '',
          points: '24,12 24,36 24,24 12,24 36,24',
          icon: '+',
          textY: 48.6
        },

        or: {
          width: 60,
          height: 60,
          text: '',
          icon: '×',
          points: '16,16 32,32 24,24 16,32 32,16',
          textY: 48.6
        }
      }

      const portConfig = {
        circle: {
          magnet: true,
          r: 4,
          stroke: '#409EFF',
          fill: '#fff',
          strokeWidth: 1,
          style: {
            visibility: 'hidden'
          }
        }
      }

      const getStartEnd = (nodeConfig, shape) => {
        return {
          inherit: 'circle',
          width: nodeConfig.width,
          height: nodeConfig.height,
          attrs: {
            body: {
              strokeWidth: nodeConfig.strokeWidth,
              stroke: '#1890FF',
              fill: '#FFF'
            },
            label: {
              text: nodeConfig.text,
              textAnchor: 'middle',
              textVerticalAnchor: 'middle',
              fill: '#262626',
              fontSize: 12
            }
          },
          markup: [
            {
              tagName: 'circle',
              selector: 'body'
            },
            // {
            //   tagName: 'text',
            //   selector: 'nodeName'
            // },
            {
              tagName: 'text',
              selector: 'label'
            }
          ],
          ports: {
            groups: {
              in: {
                position: 'ellipseSpread',
                attrs: {
                  circle: portConfig.circle
                },
                zIndex: 8
              },
              out: {
                position: 'ellipseSpread',
                attrs: {
                  circle: portConfig.circle
                }
              }
            },
            items: [
              {
                id: 'port1',
                group: shape === 'start' ? 'out' : 'in',
                zIndex: 8
              },
              {
                id: 'port2',
                group: shape === 'start' ? 'out' : 'in'
              },
              {
                id: 'port3',
                group: shape === 'start' ? 'out' : 'in'
              },
              {
                id: 'port4',
                group: shape === 'start' ? 'out' : 'in'
              }
            ]
          }
        }
      }

      const getGateway = (nodeConfig) => {
        return {
          inherit: 'polygon',
          width: nodeConfig.width,
          height: nodeConfig.height,
          attrs: {
            body: {
              strokeWidth: 2,
              stroke: '#5F95FF',
              refPoints: '0,24 24,0 48,24 24,48'
            },
            icon: {
              stroke: '#5F95FF',
              fill: '#5F95FF',
              fontSize: 40,
              text: nodeConfig.icon
            },
            nodeName: {
              fontSize: 12,
              text: nodeConfig.text,
              x: 0,
              y: nodeConfig.textY,
              refX: 0.5,
              textAnchor: 'middle',
              textVerticalAnchor: 'middle'
            }
          },
          markup: [
            {
              tagName: 'polygon',
              selector: 'body'
            },
            {
              tagName: 'text',
              selector: 'icon'
            },
            {
              tagName: 'text',
              selector: 'nodeName'
            }
          ],
          ports: {
            groups: {
              all: {
                position: 'absolute',
                attrs: {
                  circle: portConfig.circle
                }
              }
            },
            items: [
              {
                id: 'port1',
                group: 'all',
                args: {
                  x: '0%',
                  y: '50%'
                }
              },
              {
                id: 'port2',
                group: 'all',
                args: {
                  x: '50%',
                  y: '0%'
                }
              },
              {
                id: 'port3',
                group: 'all',
                args: {
                  x: '100%',
                  y: '50%'
                }
              },
              {
                id: 'port4',
                group: 'all',
                args: {
                  x: '50%',
                  y: '100%'
                }
              }
            ]
          }
        }
      }

      // 开始事件
      Graph.registerNode(
        'start-event',
        getStartEnd(nodeConfig.start, 'start'),
        true
      )

      // 结束事件
      Graph.registerNode(
        'end-event',
        getStartEnd(nodeConfig.end, 'end'),
        true
      )

      // 排他网关
      Graph.registerNode(
        'exclusive-gateway',
        getGateway(nodeConfig.or),
        true
      )

      // 并行网关
      Graph.registerNode(
        'parallel-gateway',
        getGateway(nodeConfig.and),
        true
      )

      // 活动
      register({
        shape: 'activity',
        width: 120,
        height: 60,
        component: ActivityNode,
        ports: {
          groups: {
            all: {
              position: 'absolute',
              attrs: {
                circle: portConfig.circle
              }
            }
          },
          items: [
            {
              id: 'port1',
              group: 'all',
              args: {
                x: '0%',
                y: '50%'
              }
            },
            {
              id: 'port2',
              group: 'all',
              args: {
                x: '50%',
                y: '0%'
              }
            },
            {
              id: 'port3',
              group: 'all',
              args: {
                x: '100%',
                y: '50%'
              }
            },
            {
              id: 'port4',
              group: 'all',
              args: {
                x: '50%',
                y: '100%'
              }
            }
          ]
        }
      })
      // 活动
      // Graph.registerNode(
      //   'activity',
      //   {
      //     inherit: 'rect',
      //     width: 120,
      //     height: 60,
      //     markup: [
      //       {
      //         tagName: 'rect',
      //         selector: 'body'
      //       },
      //       {
      //         tagName: 'image',
      //         selector: 'img'
      //       },
      //       {
      //         tagName: 'text',
      //         selector: 'label'
      //       }
      //     ],
      //     attrs: {
      //       body: {
      //         rx: 6,
      //         ry: 6,
      //         stroke: '#5F95FF',
      //         fill: '#EFF4FF',
      //         strokeWidth: 1
      //       },
      //       img: {
      //         x: 6,
      //         y: 6,
      //         width: 16,
      //         height: 16,
      //         'xlink:href':
      //           'https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*pwLpRr7QPGwAAAAAAAAAAAAAARQnAQ'
      //       },
      //       label: {
      //         text: '审批人',
      //         fontSize: 12,
      //         fill: '#262626',
      //         textWrap: {
      //           width: '100%',
      //           height: '50%', // 高度为参照元素高度的一半
      //           ellipsis: true, // 文本超出显示范围时，自动添加省略号
      //           breakWord: true
      //         }
      //       }
      //     },
      //     ports: {
      //       groups: {
      //         all: {
      //           position: 'absolute',
      //           attrs: {
      //             circle: portConfig.circle
      //           }
      //         }
      //       },
      //       items: [
      //         {
      //           id: 'port1',
      //           group: 'all',
      //           args: {
      //             x: '0%',
      //             y: '50%'
      //           }
      //         },
      //         {
      //           id: 'port2',
      //           group: 'all',
      //           args: {
      //             x: '50%',
      //             y: '0%'
      //           }
      //         },
      //         {
      //           id: 'port3',
      //           group: 'all',
      //           args: {
      //             x: '100%',
      //             y: '50%'
      //           }
      //         },
      //         {
      //           id: 'port4',
      //           group: 'all',
      //           args: {
      //             x: '50%',
      //             y: '100%'
      //           }
      //         }
      //       ]
      //     }
      //   },
      //   true
      // )
    },

    addNodeEvent() {
      this.showPortsEvent()
      this.nodeClick()
      this.canvasClickEvent()
      this.edgesClickEvent()
      this.canvasScale()
      this.historyChange()
      this.edgesMouseEnterEvent()
      this.bindKeyboard()
      this.edgeCreate()
      this.nodeRemoved()
    },

    // 监听节点或边的删除
    nodeRemoved() {
      this.graph.on('cell:removed', ({ cell, index, options }) => {
        this.configurationType = 'base'
      })
    },

    showPortsEvent() {
      const changePortsVisible = (visible) => {
        const container = document.getElementById('graph')
        const ports = container.querySelectorAll('.x6-port-body')
        for (let i = 0, len = ports.length; i < len; i = i + 1) {
          ports[i].style.visibility = visible ? 'visible' : 'hidden'
        }
      }

      this.graph.on('node:mouseenter', () => {
        changePortsVisible(true)
      })

      this.graph.on('node:mouseleave', () => {
        changePortsVisible(false)
      })
    },

    nodeClick() {
      this.graph.on('node:click', ({ e, x, y, node, view }) => {
        console.log('node --------->', node)
        if (this.currentEdge) {
          this.currentEdge.removeTools()
          this.currentEdge.setAttrs({
            line: {
              stroke: 'black'
            }
          })
          this.currentEdge = null
        }
        const toolOptions = [
          {
            name: 'button-remove',
            args: {
              x: '100%',
              y: 0,
              offset: {
                x: 10,
                y: -10
              }
            }
          },
          {
            name: 'boundary',
            args: {
              padding: 5,
              attrs: {
                fill: 'none',
                stroke: '#239edd',
                'stroke-width': 2
                // 'fill-opacity': 0.2
              }
            }
          }
        ]

        if (this.currentNode) {
          this.currentNode.removeTools()
          node.addTools(toolOptions)

          this.currentNode = node

          // this.showEditNodeDrawer = true
        } else {
          // this.showEditNodeDrawer = true
          node.addTools(toolOptions)
          this.currentNode = node
        }

        if (node.shape === 'start-event' || node.shape === 'end-event') return

        const configType = {
          'start-event': 'common',
          'end-event': 'common',
          'activity': 'activity',
          'exclusive-gateway': 'common',
          'parallel-gateway': 'common'
        }
        this.configurationType = configType[node.shape]
        console.log('this.currentNode.getData() --------->', this.currentNode.getData())
        this.currentNodeData = cloneDeep(this.currentNode.getData())
      })

      this.graph.on('node:contextmenu', ({ e, x, y, node, view }) => {
        const toolOptions = [
          {
            name: 'button-remove',
            args: {
              x: '100%',
              y: 0,
              offset: {
                x: 10,
                y: -10
              }
            }
          },
          {
            name: 'boundary',
            args: {
              padding: 5,
              attrs: {
                fill: 'none',
                stroke: '#409EFF',
                'stroke-width': 1,
                'fill-opacity': 0.2
              }
            }
          }
        ]

        if (this.currentNode) {
          this.currentNode.removeTools()
          node.addTools(toolOptions)
          this.currentNode = node
        } else {
          node.addTools(toolOptions)
          this.currentNode = node
        }
      })
    },

    canvasClickEvent() {
      this.graph.on('blank:click', ({ e, x, y }) => {
        this.configurationType = 'base'
        if (this.currentNode) {
          this.currentNode.removeTools()
          this.currentNode = null
        }

        if (this.currentEdge) {
          this.currentEdge.removeTools()
          this.currentEdge.setAttrs({
            line: {
              stroke: 'black'
            }
          })
          this.currentEdge = null
        }
      })
    },

    edgesClickEvent() {
      this.graph.on('edge:click', ({ edge, cell }) => {
        this.nodeToolsRemove()

        const tools = [
          {
            name: 'boundary',
            args: {
              padding: 5,
              attrs: {
                fill: '#409EFF',
                stroke: '#409EFF',
                'stroke-width': 1,
                'fill-opacity': 0.2
              }
            }
          }
        ]

        if (this.currentEdge) {
          this.currentEdge.removeTools()
          this.currentEdge.setAttrs({
            line: {
              stroke: 'black'
            }
          })

          cell.setAttrs({
            line: {
              stroke: '#409EFF'
            }
          })
          cell.addTools(tools)
          this.currentEdge = edge
          // this.showEditNodeDrawer = true
        } else {
          cell.setAttrs({
            line: {
              stroke: '#409EFF'
            }
          })
          cell.addTools(tools)
          this.currentEdge = edge

          // this.showEditNodeDrawer = true
        }
        this.configurationType = 'common'
        this.currentNodeData = cloneDeep(this.currentEdge.getData())
      })
    },

    edgesMouseEnterEvent() {
      this.graph.on('edge:mouseenter', ({ cell }) => {
        const tools = [
          {
            name: 'source-arrowhead',
            args: {
              tagName: 'rect',
              attrs: {
                fill: '#31d0c6',
                stroke: '#31d0c6',
                y: -1,
                width: 11,
                height: 2
              }
            }
          },
          {
            name: 'target-arrowhead',
            args: {
              attrs: {
                'stroke-width': 1,
                fill: '#31d0c6',
                d: 'M -12 -8 3 0 -12 8 -9 0 Z'
              }
            }
          },
          {
            name: 'button-remove',
            args: {
              x: '100%',
              y: 0,
              offset: {
                x: 0,
                y: 0
              }
            }
          }
        ]

        cell.setAttrs({
          line: {
            stroke: '#409EFF'
          }
        })

        cell.addTools(tools)
      })

      this.graph.on('edge:mouseleave', ({ cell }) => {
        cell.setAttrs({
          line: {
            stroke: 'black'
          }
        })
        cell.removeTool('button-remove')
        cell.removeTool('source-arrowhead')
        cell.removeTool('target-arrowhead')
      })
    },

    canvasScale() {
      this.graph.on('scale', ({ sx, sy, ox, oy }) => {
        this.currentZoomScale = sx
      })
    },

    historyChange() {
      this.graph.on('history:change', () => {
        this.historyState.canRedo = this.graph.canRedo()
        this.historyState.canUndo = this.graph.canUndo()
      })
    },

    // 连接线创建
    edgeCreate() {
      this.graph.on('edge:added', ({ cell }) => {
        cell.setData({
          name: ''
        })
      })
    },

    // 绑定快捷键
    bindKeyboard() {
      // 撤销
      this.graph.bindKey('ctrl+z', (e) => {
        this.graph.undo()
        return false
      }, 'keydown')

      // 恢复
      this.graph.bindKey('ctrl+y', (e) => {
        this.graph.redo()
        return false
      }, 'keydown')

      // 放大
      this.graph.bindKey('ctrl+=', (e) => {
        e.preventDefault()
        if (this.currentZoomScale >= 2.0) return
        this.graph.zoomTo(this.currentZoomScale + 0.1)
        return false
      }, 'keydown')

      // 缩小
      this.graph.bindKey('ctrl+-', (e) => {
        e.preventDefault()
        if (parseFloat(this.currentZoomScale.toFixed(2)) <= 0.1) return
        this.graph.zoomTo(this.currentZoomScale - 0.1)
        return false
      }, 'keydown')

      // 删除
      this.graph.bindKey(['Delete', 'Backspace'], (e) => {
        const selectedNodes = this.graph.getSelectedCells()
        selectedNodes.forEach(node => this.graph.removeNode(node))
        return false
      }, 'keyup')
    },

    nodeToolsRemove() {
      const nodes = this.graph.getNodes()
      nodes.forEach(node => node.removeTools())
    },

    edgesRemove() {
      const edges = this.graph.getEdges()
      edges.forEach(edge => {
        edge.removeTools()
        edge.setAttrs({
          line: {
            stroke: 'black'
          }
        })
      })
    }
  }
}
